package com.whh.downloader;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.google.gson.Gson;
import com.whh.downloader.model.Ability;
import com.whh.downloader.model.Hero;
import com.whh.downloader.model.Item;

public class Dota2HtmlParser {
	private static final Logger logger = Logger.getLogger(Dota2HtmlParser.class);
	private static final String ABILITY_IMG_PATH = "F://素材//dota2//abilities//";
	private static final String HERO_JSON_PATH = "F://素材//dota2//";
	private static final String ITEM_JSON_PATH = "F://素材//dota2//";
	private static final String HERO_HEADERS_PATH = "F:/素材//dota2//heros//";
	private static final String ITEM_IMGS_PATH = "F:/素材//dota2//items//";
	
	public static void main(String[] args) {
		//System.out.println(new Gson().toJsonTree(parseHero("http://www.dota2.com/hero/Invoker/", false)));
		parseTypeAndGroup();
	}
	
	/**
	 * 下载所有英雄的头像(大图和小图)
	 */
	public static void downloadHeroHeaders(){
		try {
			Document doc = Jsoup.connect("http://www.dota2.com/heroes/").get();
			Element heroPickerInner = doc.getElementById("heroPickerInner");
			Elements imgs = heroPickerInner.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				Element e = imgs.get(i);
				String src = e.attr("src");
				if(src.indexOf("sb.png")>0){
					ImgDownloader.downloadImg(src, HERO_HEADERS_PATH,null);
					ImgDownloader.downloadImg(src.replace("sb.png", "vert.jpg"), HERO_HEADERS_PATH,null);
				}
			}
		} catch (IOException e) {
			logger.error("下载所有英雄的头像出错",e);
		}
	}
	
	/**
	 * 下载所有物品的图片
	 */
	public static void downloadItemImgs(){
		try {
			Document doc = Jsoup.connect("http://www.dota2.com/items/").get();
			Element itemPickerInner = doc.getElementById("itemPickerInner");
			Elements imgs = itemPickerInner.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				Element e = imgs.get(i);
				String src = e.attr("src");
				ImgDownloader.downloadImg(src, ITEM_IMGS_PATH,null);
			}
		} catch (IOException e) {
			logger.error("下载所有物品的图片出错",e);
		}
	}
	
	public static void parseTypeAndGroup(){
		try{
			Document doc = Jsoup.connect("http://www.dota2.com/heroes/").get();
			Element heroPickerInner = doc.getElementById("heroPickerInner");
			Element heroColLeft0 = heroPickerInner.select("div[class=heroColLeft]").get(0);
			Element heroColLeft1 = heroPickerInner.select("div[class=heroColLeft]").get(1);
			Element heroColMiddle0 = heroPickerInner.select("div[class=heroColMiddle]").get(0);
			Element heroColMiddle1 = heroPickerInner.select("div[class=heroColMiddle]").get(1);
			Element heroColRight0 = heroPickerInner.select("div[class=heroColRight]").get(0);
			Element heroColRight1 = heroPickerInner.select("div[class=heroColRight]").get(1);
			
			Elements imgs = null;
			imgs = heroColLeft0.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				String src = imgs.get(i).attr("src");
				if(src.indexOf("hphover")>0){
					System.out.println(src.substring(src.lastIndexOf("/")+1,src.lastIndexOf(".")).replace("hphover", "vert")+",1,3");
				}
			}
			imgs = heroColLeft1.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				String src = imgs.get(i).attr("src");
				if(src.indexOf("hphover")>0){
					System.out.println(src.substring(src.lastIndexOf("/")+1,src.lastIndexOf(".")).replace("hphover", "vert")+",2,3");
				}
			}
			imgs = heroColMiddle0.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				String src = imgs.get(i).attr("src");
				if(src.indexOf("hphover")>0){
					System.out.println(src.substring(src.lastIndexOf("/")+1,src.lastIndexOf(".")).replace("hphover", "vert")+",1,2");
				}
			}
			imgs = heroColMiddle1.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				String src = imgs.get(i).attr("src");
				if(src.indexOf("hphover")>0){
					System.out.println(src.substring(src.lastIndexOf("/")+1,src.lastIndexOf(".")).replace("hphover", "vert")+",2,2");
				}
			}
			imgs = heroColRight0.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				String src = imgs.get(i).attr("src");
				if(src.indexOf("hphover")>0){
					System.out.println(src.substring(src.lastIndexOf("/")+1,src.lastIndexOf(".")).replace("hphover", "vert")+",1,1");
				}
			}
			imgs = heroColRight1.select("img[src$=.png]");
			for(int i=0;i<imgs.size();i++){
				String src = imgs.get(i).attr("src");
				if(src.indexOf("hphover")>0){
					System.out.println(src.substring(src.lastIndexOf("/")+1,src.lastIndexOf(".")).replace("hphover", "vert")+",2,1");
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 导出英雄信息到json
	 */
	public static void exportHerosJson(boolean isDownloadImg){
		List<Hero> heros = new ArrayList<Hero>();
		List<String> urls = getHeroUrls();
		int i= 0;
		for(String url:urls){
			Hero hero = parseHero(url,isDownloadImg);
			while(hero==null){
				i++;
				logger.error("解析失败,重新解析:url="+url);
				hero = parseHero(url,isDownloadImg);
			}
			logger.info(new Gson().toJson(hero));
			heros.add(hero);
		}
		logger.info("重新解析次数:"+i);
		try{
			// 存放地址
			File folder = new File(HERO_JSON_PATH);
			if(!folder.exists()){
				folder.mkdir();
			}
			File json = new File(HERO_JSON_PATH+"heros.json");
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(json)));
			bw.write(new Gson().toJson(heros));
			bw.flush();
			bw.close();
			logger.info("导出英雄信息到json["+json.getPath()+"]");
		}catch(Exception e){
			logger.error("导出英雄信息到json出错",e);
		}
	}
	
	/**
	 * 导出物品信息到json
	 */
	public static void exportItemsJson(){
		String url = "http://www.dota2.com/jsfeed/itemdata?v=1586714&l=english";
		String folderPath = ITEM_JSON_PATH;
		try {
			URL u = new URL(url);
		    BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream()));
		    StringBuffer sb = new StringBuffer();
		    String str;
		    while((str=in.readLine())!=null){
		    	sb.append(str);
		    }
		    in.close();
		    Map<String,Object> map = new Gson().fromJson(sb.toString(),Map.class);
		    Iterator<String> iter = map.keySet().iterator();
		    List<Item> items = new ArrayList<Item>();
		    while(iter.hasNext()){
		    	Item item = new Item();
		    	String key = iter.next().toString();
		    	Map<String,Object> m = (Map<String,Object>)map.get(key);
		    	item.setImg(m.get("img").toString());
		    	item.setName(m.get("dname").toString());
		    	item.setQual(m.get("qual").toString());
		    	item.setCost(m.get("cost").toString());
		    	item.setDesc(m.get("desc").toString());
		    	item.setAtrrib(m.get("attrib").toString());
		    	item.setMc(m.get("mc") instanceof Boolean?"false":m.get("mc").toString());
		    	item.setCd(m.get("cd") instanceof Boolean?"false":m.get("cd").toString());
		    	item.setLore(m.get("lore").toString());
		    	item.setComponents(m.get("components")==null?new String[0]:m.get("components").toString().split(","));
		    	items.add(item);
		    }
			// 存放地址
			File folder = new File(folderPath);
			if(!folder.exists()){
				folder.mkdir();
			}
			File json = new File(folderPath + "items.json");
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(json)));
			bw.write(new Gson().toJson(items));
			bw.flush();
			bw.close();
			logger.info("导出物品信息到json["+json.getPath()+"]");
		} catch (Exception e) {
			logger.error("导出物品信息到json error["+url+"]",e);
		}
	}
	
	public static List<String> getHeroUrls(){
		List<String> list = new ArrayList<String>();
		try {
			Document doc = Jsoup.connect("http://www.dota2.com/heroes/").get();
			Element heroPickerInner = doc.getElementById("heroPickerInner");
			Elements as = heroPickerInner.select("a[class=heroPickerIconLink]");
			for(int i=0;i<as.size();i++){
				Element a = as.get(i);
				String href = a.attr("href");
				list.add(href);
			}
		} catch (IOException e) {
			logger.error("获取所有英雄URL出错",e);
		}
		return list;
	}
	
	/**
	 * 解析指定url中的英雄
	 * @param url
	 * @return
	 */
	public static Hero parseHero(String url,boolean isDownloadImg){
		Hero hero = new Hero();
		try {
			Document doc = Jsoup.connect(url).get();
			Element content = doc.getElementById("centerColContent");
			//英文名称
			String nameEn = content.select("h1").get(0).text().trim().toUpperCase();
			hero.setNameEn(nameEn);
			//攻击类型和角色
			Element heroBioRoles = content.getElementById("heroBioRoles");
			String attackType = heroBioRoles.select("span[class=bioTextAttack]").get(0).text().trim();
			hero.setAttackType(attackType.equals("Melee")?Constant.ATTACK_TYPE_MELEE:Constant.ATTACK_TYPE_RANGED);
			String roles = heroBioRoles.text().trim().substring(heroBioRoles.text().trim().indexOf("-")+2, heroBioRoles.text().trim().length());
			hero.setRoles(roles);
			//头像
			Element heroPrimaryPortraitImg = content.getElementById("heroPrimaryPortraitImg");
			String imgUrl = heroPrimaryPortraitImg.attr("src");
			hero.setHeaderVert(imgUrl.substring(imgUrl.lastIndexOf("/")+1, imgUrl.lastIndexOf(".")));
			//初始状态
			Element overviewPrimaryStats = content.getElementById("overviewPrimaryStats");
			Element overviewIcon_Primary = overviewPrimaryStats.getElementById("overviewIcon_Primary");
			String style = overviewIcon_Primary.attr("style");
			if(style.trim().equals("top:83px")){
				hero.setType(Constant.HERO_TYPE_STR);
			}else if(style.trim().equals("top:43px")){
				hero.setType(Constant.HERO_TYPE_AGI);
			}else if(style.trim().equals("top:1px")){
				hero.setType(Constant.HERO_TYPE_INT);
			}
			Element overview_IntVal = overviewPrimaryStats.getElementById("overview_IntVal");
			Integer intelligence = Integer.parseInt(overview_IntVal.text().split("\\+")[0].trim());
			Double intelligenceIncrease = Double.parseDouble(overview_IntVal.text().split("\\+")[1].trim());
			Element overview_AgiVal = overviewPrimaryStats.getElementById("overview_AgiVal");
			Integer agility = Integer.parseInt(overview_AgiVal.text().split("\\+")[0].trim());
			Double agilityIncrease = Double.parseDouble(overview_AgiVal.text().split("\\+")[1].trim());
			Element overview_StrVal = overviewPrimaryStats.getElementById("overview_StrVal");
			Integer strength = Integer.parseInt(overview_StrVal.text().split("\\+")[0].trim());
			Double strengthIncrease = Double.parseDouble(overview_StrVal.text().split("\\+")[1].trim());
			Element overview_AttackVal = overviewPrimaryStats.getElementById("overview_AttackVal");
			Integer attackMin = Integer.parseInt(overview_AttackVal.text().split("\\-")[0].trim());;
			Integer attackMax = Integer.parseInt(overview_AttackVal.text().split("\\-")[1].trim());;;
			Element overview_SpeedVal = overviewPrimaryStats.getElementById("overview_SpeedVal");
			Integer movespeed = Integer.parseInt(overview_SpeedVal.text().trim());;;
			Element overview_DefenseVal = overviewPrimaryStats.getElementById("overview_DefenseVal");
			Double defense = Double.parseDouble(overview_DefenseVal.text().trim());
			hero.setIntelligence(intelligence);
			hero.setIntelligenceIncrease(intelligenceIncrease);
			hero.setAgility(agility);
			hero.setAgilityIncrease(agilityIncrease);
			hero.setStrength(strength);
			hero.setStrengthIncrease(strengthIncrease);
			hero.setAttackMin(attackMin);
			hero.setAttackMax(attackMax);
			hero.setMoveSpeed(movespeed);
			hero.setDefense(defense);
			//视野、攻击距离、弹道速度
			Element statsRight = content.getElementById("statsRight");
			Elements stats = statsRight.select("div[class=statRowCol2W]");
			Integer sightRangeDay = Integer.parseInt(stats.get(0).text().split("\\/")[0].trim());
			Integer sightRangeNight = Integer.parseInt(stats.get(0).text().split("\\/")[1].trim());
			Integer attackRange = Integer.parseInt(stats.get(1).text().trim());
			Integer missileSpeed = stats.get(2).text().trim().equals("N/A")?0:Integer.parseInt(stats.get(2).text().trim());
			hero.setSightRangeDay(sightRangeDay);
			hero.setSightRangeNight(sightRangeNight);
			hero.setAttackRange(attackRange);
			hero.setMissileSpeed(missileSpeed);
			//英雄故事
			Element bioInner = content.getElementById("bioInner");
			hero.setBio(bioInner.text().trim());
			//技能
			List<Ability> abilities = new ArrayList<Ability>();
			Element abilitiesInner = content.getElementById("abilitiesInner");
			Elements abilitiesInsetBoxContents = abilitiesInner.select("div[class=abilitiesInsetBoxContent]");
			for(int i=0;i<abilitiesInsetBoxContents.size();i++){
				Element box = abilitiesInsetBoxContents.get(i);
				Ability ability = new Ability();
				String abilityImgUrl = box.select("img[class=overviewAbilityImg]").get(0).attr("src").replace("hp2.png", "hp1.png");
				ability.setImg(abilityImgUrl.substring(abilityImgUrl.lastIndexOf("/")+1,abilityImgUrl.lastIndexOf(".")));
				if(isDownloadImg){
					ImgDownloader.downloadImg(abilityImgUrl,ABILITY_IMG_PATH,null);
				}
				Element abilityHeaderRowDescription = box.select("div[class=abilityHeaderRowDescription]").get(0);
				String name = abilityHeaderRowDescription.select("h2").get(0).text().trim();
				String desc = abilityHeaderRowDescription.select("p").get(0).text().trim();
				ability.setName(name);
				ability.setDesc(desc);
				Elements mana = box.select("div[class=mana]");
				if(mana!=null && mana.size()>0){
					ability.setManaCost(mana.get(0).text().trim().substring(11,mana.get(0).text().trim().length()));
				}
				Elements cooldown = box.select("div[class=cooldown]");
				if(cooldown!=null && cooldown.size()>0){
					ability.setCoolDown(cooldown.get(0).text().trim().substring(10,cooldown.get(0).text().trim().length()));
				}
				Elements abilityFooterBox = box.select("div[class=abilityFooterBox]");
				if(abilityFooterBox!=null && abilityFooterBox.size()>0){
					Elements attribVals = abilityFooterBox.get(0).select("span[class=attribVal]");
					String effectStr = "";
					for(int n=0;n<attribVals.size();n++){
						String value = attribVals.get(n).text().trim();
						String key = attribVals.get(n).previousSibling().toString().trim();
						Element scepterElement = attribVals.get(n).previousElementSibling();
						if(scepterElement!=null){
							String scepter = scepterElement.text();
							if(scepter!=null && !scepter.equals("")){
								key = scepter;
							}
						}
						if(key!=null && !key.equals("")){
							effectStr=effectStr+key+value+";";
						}
					}
					ability.setEffect(effectStr);
				}
				abilities.add(ability);
			}
			hero.setAbilities(abilities);
			
		} catch (IOException e) {
			logger.error("解析英雄出错,url="+url,e);
			return null;
		}
		return hero;
	}
}
